﻿using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace AudioSourceManager
{
    internal class UdpStreamReader
    {
        //接收数据事件
        public Action<byte[]> OnRecvMessage = null;
        //本地监听端口
        public int destPort = 0;
        //组播地址
        public string MultiCastHost = "";

        private UdpClient udpClient = null;

        public UdpStreamReader(string url)
        {
            if (URLReader.TryResolve(url, out var reader))
            {
                this.destPort = reader.Port;
                this.MultiCastHost = reader.IP;
                if (this.destPort < 0 || this.destPort > 65535)
                    throw new ArgumentOutOfRangeException("localPort is out of range");
                if (string.IsNullOrEmpty(this.MultiCastHost))
                    throw new ArgumentNullException("message cant not null");
            }
            else
            {
                throw new ArgumentException("url cant resolve");
            }

        }

        public void Start()
        {
            while (true)
            {
                try
                {

                    // 定义组播接收端
                    udpClient = new UdpClient(AddressFamily.InterNetwork);
                    // 端口复用：设置只监听此端口，不独占此端口
                    udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                    udpClient.ExclusiveAddressUse = false;
                    // 绑定端口
                    udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, destPort));
                    // 加入多播组
                    udpClient.JoinMulticastGroup(IPAddress.Parse(MultiCastHost));
                    ReceiveMessage();
                    break;
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message.ToString());
                    Thread.Sleep(100);
                }
            }
        }



        private async void ReceiveMessage()
        {
            while (true)
            {
                if (udpClient == null)
                    return;

                try
                {
                    UdpReceiveResult udpReceiveResult = await udpClient.ReceiveAsync();
                    byte[] message = udpReceiveResult.Buffer;
                    if (OnRecvMessage != null)
                        OnRecvMessage(message);
                }
                catch (Exception ex)
                {
                }
            }
        }

        public void CloseUdpCliend()
        {
            if (udpClient == null)
                throw new ArgumentNullException("udpClient cant not null");

            try
            {
                udpClient.Client.Shutdown(SocketShutdown.Both);
            }
            catch (Exception)
            {
            }
            udpClient.Close();
            udpClient = null;
        }

        internal void Stop()
        {
            throw new NotImplementedException();
        }
    }
}
